import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.BindException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Date;

import org.omg.CORBA.portable.OutputStream;


public final class WebServer {

    public static void main(String argv[]) throws Exception
    {
		// Establish the listen socket.
	    ServerSocket welcomeSocket = null;
	    
	    try {
			welcomeSocket = new ServerSocket(6789);
		} catch (BindException e) {
			System.out.println("Web server failed to start.  Port already in use.  Choose another port.");
			return;
		}
		catch (Exception e) {
			System.out.println("Web server failed to start. " + e.getLocalizedMessage() );
			e.printStackTrace();
			return;
		}
    	System.out.println("Web server started");
	    
    	
    	// Process HTTP service requests in an infinite loop.
    	while (true) {
    		// Listen for a TCP connection request.
    		Socket connectionSocket = welcomeSocket.accept(); 

    		// Construct an object to process the HTTP request message.
    		HttpRequest request = new HttpRequest( connectionSocket );
    		 
    		// Create a new thread to process the request.
    		Thread thread = new Thread(request);
    		 
    		// Start the thread.
    		thread.start();  		
    	}
    }
}

final class HttpRequest implements Runnable
{
    final static String CRLF = "\r\n";
    Socket socket;

    // Constructor
    public HttpRequest(Socket socket) throws Exception 
    {
           this.socket = socket;
    }

    // Implement the run() method of the Runnable interface.
    public void run()
    {
 		try {
			processRequest();
		} catch (Exception e) {
			System.err.println("Error processing the web request:  " + e.getMessage());
			e.printStackTrace();
		}
		finally{
			try {
				this.socket.close();
			} catch (IOException e) {
				System.err.println("Unable to close socket connection");
			}
		}
    }

    private void processRequest() throws Exception
    {
    	System.out.println("Thread " + Thread.currentThread().getId());
    	System.out.println("*********** Begin Request **************");
        // Get a reference to the socket's input and output streams.
        //InputStream is = ?;
        //DataOutputStream os = ?;

        BufferedReader is = 
            new BufferedReader(new
            InputStreamReader(socket.getInputStream())); 

        String requestLine = is.readLine();
         
        // Display the request line.
        System.out.println(requestLine);
         
        // Get and display the header lines.
        String headerLine = null;
        while ((headerLine = is.readLine()).length() != 0) {
                System.out.println(headerLine);
        }
        
    	System.out.println("************ End Request *************\n\n");
    	
    	// I am going to refactor this and move to a separate method - processResponse
    	PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
    	
    	out.println("Here is a response - " + new Date().toLocaleString() + CRLF);
    	
    	is.close();
    	out.close();
    }

}
